﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;

namespace VendingMachineLib
{
    public abstract class TypedStacks<T> : IEnumerable<T>
    {
        protected readonly Dictionary<Type, Stack<T>> _stacks = new Dictionary<Type, Stack<T>>();

        protected TypedStacks(IEnumerable<Type> types)
        {
            ClearInternal(types);
        }

        public void Clear()
        {
            var types = _stacks.Keys.ToList();
            ClearInternal(types);
        }

        private void ClearInternal(IEnumerable<Type> types)
        {
            _stacks.Clear();
            foreach (var type in types)
            {
                _stacks.Add(type, new Stack<T>());
            }
        }

        public IEnumerator<T> GetEnumerator()
        {
            var all = new List<T>();
            foreach (var productStack in _stacks)
            {
                all.AddRange(productStack.Value);
            }
            return new ReadOnlyCollection<T>(all).GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public void AddRange(IEnumerable<T> items)
        {
            foreach (var item in items)
            {
                Add(item);
            }
        }

        public void Add(T item)
        {
            var type = item.GetType();
            var stack = _stacks[type];
            stack.Push(item);
        }


        public T Peek<TS>() where TS : class, T
        {
            var stack = _stacks[typeof(TS)]; 
            return stack.Peek();
        }

        public T Pop<TS>() where TS : class, T
        {
            var stack = _stacks[typeof(TS)];
            return stack.Pop();
        }

        public int Count<TS>() where TS : class, T
        {
            var stack = _stacks[typeof(TS)];
            return stack.Count;
        }
    }

}
